import es
import nativetools as nt
import gamethread
import random

import aaauth
reload(aaauth)
import aanativetoolslib as aant
reload(aant)

ninjas  = []
heavies = []
muted   = []

class UseridError(Exception):
    pass

class Filter(object):
    def __init__(self, tag):
        self.tag = tag
        #if tag in ['@all', '@ct', '@t', '@spec', '@specs', '@alive', '@dead', '@human', '@humans', '@bot', '@bots', '@admin', '@admins']:
        #    if tag == '@all':
        #        es.getUseridList()
        #    elif tag == '@ct':
        #        self.ct()
        #    elif tag == '@t':
        #        self.t()
        #    elif tag == '@spec' or tag == '@specs':
        #        self.spec()
        #    elif tag == '@alive':
        #        self.alive()
        #    elif tag == '@dead':
        #        self.dead()
        #    elif tag == '@human' or tag == '@humans':
        #        self.human()
        #    elif tag == '@bot' or tag == '@bots':
        #        self.bots()
        #    elif tag == '@admin' or tag == '@admins':
        #        self.admins()
    def process(self):
        if self.tag in ['@all', '@ct', '@t', '@spec', '@specs', '@alive', '@dead', '@human', '@humans', '@bot', '@bots', '@admin', '@admins']:
            if self.tag == '@all':
                return es.getUseridList()
            elif self.tag == '@ct':
                return filter(lambda x: es.getplayerteam(x) == 3, es.getUseridList())
            elif self.tag == '@t':
                return filter(lambda x: es.getplayerteam(x) == 2, es.getUseridList())
            elif self.tag == '@spec' or self.tag == '@specs':
                return filter(lambda x: es.getplayerteam(x) == 1, es.getUseridList())
            elif self.tag == '@alive':
                return filter(lambda x: not es.getplayerprop(x, 'CBasePlayer.pl.deadflag'), es.getUseridList())
            elif self.tag == '@dead':
                return filter(lambda x: es.getplayerprop(x, 'CBasePlayer.pl.deadflag'), es.getUseridList())
            elif self.tag == '@human' or self.tag == '@humans':
                return filter(lambda x: es.getplayersteamid(x) != 'BOT', es.getUseridList())
            elif self.tag == '@bot' or self.tag == '@bots':
                return filter(lambda x: es.getplayersteamid(x) == 'BOT', es.getUseridList())
            elif self.tag == '@admin' or self.tag == '@admins':
                return filter(lambda x: aaauth.isAuthed(x), es.getUseridList())
        else: 
            return [es.getuserid(self.tag)]

def filters(tag):
    return Filter(tag).process()

class Player(object):
    def __init__(self, userid):
        self.userid = userid
    def fire(self, command):
        es.server.queuecmd('es_xfire %s %s' % (self.userid, command))
    def give(self, command):
        es.server.queuecmd('es_xgive %s %s' % (self.userid, command))
        
    def strip(self, weapons=['weapon_knife'], keepknife=True):
        entities = es.createentitylist()
        handle = es.getplayerhandle(self.userid)
        for entity in filter(lambda entity: entities[entity]['classname'].startswith('weapon_') and entities[entity]['classname'] not in weapons, entities): 
            if es.getindexprop(entity, 'CBaseEntity.m_hOwnerEntity') == handle: 
                es.server.queuecmd('es_xremove %s'%entity)
        if len(weapons):
            es.sexec(self.userid, 'use %s'%weapons[0])
        """
        entlist = es.createentitylist()
        entlist_temp = entlist.copy()
        for entity in entlist_temp:
            if entlist_temp[entity]['classname'] not in weapons:
                del entlist[entity]
        handle = es.getplayerhandle(self.userid)
        for index in entlist:
            if es.getindexprop(index, 'CBaseEntity.m_hOwnerEntity') == handle:
                es.server.queuecmd('es_xremove %s'%index)
            es.msg(entlist[index]['classname'])
        """
        """
        handle = es.getplayerhandle(self.userid)
        weapons = []
        for weapon in getWeaponList('#all'):
            if weapon == 'weapon_knife': continue
            for index in weapon.indexlist:
                if es.getindexprop(index, 'CBaseEntity.m_hOwnerEntity') == handle:
                    es.server.queuecmd('es_xremove %s'%index)
                    break
        es.sexec(self.userid, 'use weapon_knife')
        """
        
    def giveWeapons(self, weapons):
        for weapon in weapons:
            self.give(weapon)
                
    def slay(self):
        # effect here
        es.sexec(self.userid, 'kill')
        
    def getTeam(self):
        return es.getplayerteam(self.userid)
        
    def swapTeam(self, kill=False):
        team = 5 - self.getTeam()
        if team in [2,3]:
            es.server.queuecmd('es_xchangeteam %i %i'%(self.userid, team)) if kill else nt.switchTeam(self.userid, team)
            
    def changeTeam(self, team, kill=False):
        if int(team) in [1,2,3]:
            es.server.queuecmd('es_xchangeteam %i %i'%(self.userid, team)) if kill else nt.switchTeam(self.userid, team)
            
    def spec(self):
        es.changeteam(self.userid, 1) if int(es.getplayerteam(self.userid) > 1) else None
        
    def kick(self, reason='Kicked by Admin'):
        es.server.queuecmd('kickid %s "%s"' % (self.userid, reason))
        
    def ban(self, banTime, reason='Banned by Admin'):
        es.server.queuecmd('banid %s %s kick "%s"' % (banTime, self.userid, reason))
        
    def setNoclip(self, value=0):
        if value is 0:
            es.setplayerprop(self.userid, 'CBaseEntity.movetype', 2) if self.getNoclip() else es.setplayerprop(self.userid, 'CBaseEntity.movetype', 8)
        else:
            es.setplayerprop(self.userid, 'CBaseEntity.movetype', 8 if value else 2)
            
    def getNoclip(self):
        return 1 if es.getplayerprop(self.userid, 'CBaseEntity.movetype') == 8 else 0
        
    def setNoblock(self, value=None):
        if value is None:
            es.setplayerprop(self.userid, 'CBaseEntity.m_CollisionGroup', 5) if self.getNoblock() else es.setplayerprop(self.userid, 'CBaseEntity.movetype', 2)
        else: 
            es.setplayerprop(self.userid, 'CBaseEntity.m_CollisionGroup', 2 if value else 5)
            
    def getNoblock(self):
        return 1 if es.getplayerprop(self.userid, 'CBaseEntity.m_CollisionGroup') == 2 else 0
        
    def setFreeze(self, value=None):
        if value is None:
            es.setplayerprop(self.userid, 'CBaseEntity.movetype', 2) if self.getFreeze() else es.setplayerprop(self.userid, 'CBaseEntity.movetype', 0)
        else:
            es.setplayerprop(self.userid, 'CBaseEntity.movetype', 0 if value else 2)
            
    def getFreeze(self):
        return 1 if es.getplayerprop(self.userid, 'CBaseEntity.movetype') == 0 else 0
        
    def setHealth(self, value):
        if value < 1:
            value = 1
        es.setplayerprop(self.userid, 'CBasePlayer.m_iHealth', value)
        
    def getHealth(self):
        return es.getplayerprop(self.userid, 'CBasePlayer.m_iHealth')
        
    def addhealth(self, value):
        self.setHealth(es.getplayerprop(self.userid, 'CBasePlayer.m_iHealth') + value)
        
    def setArmor(self, value):
        if value >= 100:
            es.server.queuecmd('es_xgive %s item_assaultsuit' % self.userid)
        es.setplayerprop(self.userid, 'CCSPlayer.m_ArmorValue', value)
        
    def addArmor(self, value):
        self.setArmor(es.getplayerprop(self.userid, 'CCSPlayer.m_ArmorValue') + value)
        
    def setSpeed(self, value):
        if value < 0:
            value = 0
        es.setplayerprop(self.userid, 'CBasePlayer.localdata.m_flLaggedMovementValue', float(value))
        
    def setCash(self, value):
        if value < 0:
            value = 0
        es.setplayerprop(self.userid, 'CCSPlayer.m_iAccount', value)
        
    def addCash(self, value):
        self.setCash(es.getplayerprop(self.userid, 'CCSPlayer.m_iAccount') + value)
        
    def slap(self, damage=1):
        es.setplayerprop(self.userid, 'CBasePlayer.localdata.m_vecBaseVelocity', '%i,%i,%i'%(random.randrange(-250, 250), random.randrange(-250, 250), random.randrange(250, 500)))
        es.server.queuecmd('damage %s %s 32' % (self.userid, damage))
        
    def respawn(self):
        nt.spawnPlayer(self.userid)
        
    def setNinja(self, state=None):
        if state is None:
            self.setSpeed(1) and ninjas.remove(int(self.userid)) if self.getNinja() else self.strip() and self.speed(2) and ninjas.append(int(self.userid))
        else:
            if state:
                self.setSpeed(2) and self.strip() and ninjas.append(int(self.userid))
            else:
                self.setSpeed(1) and ninjas.remove(int(self.userid))
        
    def getNinja(self):
        return 1 if self.userid in ninjas else 0
        
    def setHeavy(self):
        self.give(['deagle', 'm249'])
        self.setSpeed(.5)
        heavies.append(int(self.userid))
    
    def getHeavy(self):
        return 1 if self.userid in ninjas else 0
        
    def burnPlayer(self, burnTime):
        self.fire('!self ignite')
        if burnTime:
            gamethread.delayed(burnTime, self.fire, '!self extinguish')
            
    def burn(self, burnTime=False):
        self.burnPlayer(burnTime)
    
    def setGod(self, value=None):
        if value is None:
            es.setplayerprop(self.userid, 'CBasePlayer.m_lifeState', 512) if self.getGod() else es.setplayerprop(self.userid, 'CBasePlayer.m_lifeState', 0)
        else:
            es.setplayerprop(self.userid, 'CBasePlayer.m_lifeState', 0 if value else 512)
            
    def getGod(self):
        return 1 if not es.getplayerprop(self.userid, 'CBasePlayer.m_lifeState') else 0
        
    def mute(self, value=None):
        if value is None:
            if self.userid in muted:
                aant.mute(self.userid, 0)
                muted.remove(self.userid)
                #es.msg('User was in muted and removed')
            else:
                aant.mute(self.userid, 1) 
                muted.append(self.userid) 
                #es.msg('Appended user')
        else:
            if value:
                if self.userid not in muted:
                    aant.mute(self.userid, 1) 
                    muted.append(self.userid)
            else: 
                if self.userid in muted:
                    aant.mute(self.userid, 0) 
                    muted.remove(self.userid)
            #aant.mute(1 if value else 0)
    
    def getMute(self):
        return 1 if self.userid in muted else 0
    
    def blind(self, time):
        es.usermsg('create', 'blind','Fade')
        es.usermsg('write', 'short', 'blind', 360) #frames to fade
        es.usermsg('write', 'short', 'blind', 750) # frames to stay faded
        es.usermsg('write', 'short', 'blind', 2) # 2 = fade in, 1 = fade out, 0 = no fade
        es.usermsg('write', 'byte', 'blind', 0) #red
        es.usermsg('write', 'byte', 'blind', 0) #green
        es.usermsg('write', 'byte', 'blind', 0) #blue
        es.usermsg('write', 'byte', 'blind', 255) #alpha
        es.usermsg('send', 'blind', self.userid)
        es.usermsg('delete', 'blind')
        self.blindtime = time
        gamethread.delayed(1, self._blindLoop)
    
    def _blindLoop(self):
        es.usermsg('create', 'blind','Fade')
        es.usermsg('write', 'short', 'blind', 1) #frames to fade
        es.usermsg('write', 'short', 'blind', 750) # frames to stay faded
        es.usermsg('write', 'short', 'blind', 0) # 2 = fade in, 1 = fade out, 0 = no fade
        es.usermsg('write', 'byte', 'blind', 0) #red
        es.usermsg('write', 'byte', 'blind', 0) #green
        es.usermsg('write', 'byte', 'blind', 0) #blue
        es.usermsg('write', 'byte', 'blind', 255) #alpha
        es.usermsg('send', 'blind', self.userid)
        es.usermsg('delete', 'blind')
        self.blindtime -= 1
        if self.blindtime > 1:
            gamethread.delayed(1, self._blindLoop)
            
    def earthquake(self, time):
        es.usermsg('create', 'earthquake', 'Shake')
        es.usermsg('write', 'byte', 'earthquake', 0)
        es.usermsg('write', 'float', 'earthquake', 50.0)
        es.usermsg('write', 'float', 'earthquake', 10.0)
        es.usermsg('write', 'float', 'earthquake', float(time))
        es.usermsg('send', 'earthquake', self.userid)
        es.usermsg('delete', 'earthquake')
    
def getPlayer(userid):
    if es.exists('userid', userid):
        return Player(userid)
    raise UseridError, 'Userid %s does not exist!' % userid
